package kr.co.redcircle.broker.io.net.Unicast;

import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocketFactory;

import org.apache.http.conn.ssl.SSLSocketFactory;

import kr.co.redcircle.broker.Broker;
import kr.co.redcircle.broker.concurrent.TPExecutor;
import kr.co.redcircle.broker.registry.Registry;
import kr.co.redcircle.broker.security.KeyCollection;
import net.sf.json.JSONObject;

public final class UnicastNetworkService {

	private static ServerSocket serverSocket;
	private static int port = -1;
	private static TPExecutor mtpe = null;
	private static String host;
	private static String cid;
	protected static boolean runFlag = true;
	private static boolean sFlag;
	private static String uIp;

	public static void init(String ip, int portInt, boolean secureFlag) {
		
		host = ip;
		cid = Registry.getCID();
		port = portInt;
		mtpe = new TPExecutor();
		sFlag = secureFlag;
		
	}

	public static void initForAdaptor(String hostString, int portInt){
		
		host = hostString;
		port = portInt;
		mtpe = new TPExecutor();		
		System.out.println("init for adaptor~!");
		
	}

	
	public static void startListener() {
		
		try {
			
			if (sFlag){
				KeyCollection kCollection = Registry.getKeyCollection();
/*				kCollection.addTrustStore("C:/Program Files/Java/jdk1.6.0_31/jre/lib/security/cacerts", "changeit");
				kCollection.setupKeyStore("C:/OpenSSL-Win64/bin/PEM/CA/USER/KIMNAMHO/KimNamHo.p12", "asdfg12qw");
				kCollection.init("asdfg12qw");
*/
				SSLContext ctx = SSLContext.getInstance("TLS");
				ctx.init(kCollection.getKeyManagers(), kCollection.getTrustManagers(), null);
				SSLServerSocketFactory sslserversocketfactory = ctx.getServerSocketFactory();
				serverSocket = sslserversocketfactory.createServerSocket(port);
			}else{
				serverSocket = new ServerSocket(port);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} catch (KeyManagementException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
			
		
		System.out.println("UNICAST System listener start!");	

		if (cid.startsWith("WORKER")){
			System.out.println("BIZ Broker 2.0 Worker Node is stared , port : " + port);
		}else if (cid.startsWith("NAME")){
			System.out.println("BIZ Broker 2.0 Name Node is stared , port : " + port);
		}else if (cid.startsWith("MONITOR")){
			System.out.println("BIZ Broker 2.0 Monitor Node is stared , port : " + port);
		}
		
		new Thread(new Runnable(){

			@Override
			public void run() {
				System.out.println("runFlag : " + runFlag);
				while(runFlag){
					try {
						mtpe.runTask(new ConnectionHandler(serverSocket.accept()));
					}catch (SocketException e){
						System.out.println("exit");
					} catch (IOException e) {					
						e.printStackTrace();
					}
				}
			}
		}).start();
				
		
	}

	public static void send(String requestString){
		JSONObject commandObject = JSONObject.fromObject(requestString);
		commandObject.put(Broker.HOST, host);
		commandObject.put(Broker.PORT, port);
		new Thread(new HostCallHandler(commandObject, true)).start();
	}

	public static void send(String tgrHost, int tgrPort, String requestString){
		JSONObject commandObject = JSONObject.fromObject(requestString);
		commandObject.put(Broker.HOST, tgrHost);
		commandObject.put(Broker.PORT, tgrPort);
		new Thread(new HostCallHandler(commandObject, true)).start();
	}

	public static String getHOST() {
		System.out.println("getHOST : " + host);
		return host;
	}

	public static int getPORT() {
		// TODO Auto-generated method stub
		return port;
	}

	public static void exit() {
		try {
			serverSocket.close();
		} catch (IOException e) {
			e.printStackTrace(); 
		}
		mtpe.shutDown();
		runFlag = false;
		
	}

	public static String sendSync(String nameNodeIp, int nameNodePort, String requestString) {
		JSONObject commandObject = JSONObject.fromObject(requestString);
		commandObject.put(Broker.HOST, nameNodeIp);
		commandObject.put(Broker.PORT, nameNodePort);
		return new SyncHostCallHandler(commandObject, true).run();
	}
	
}
